
package com.dkm.modules.sys.role.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dkm.exception.ServiceException;
import com.dkm.modules.sys.common.mapper.UniqueKeyDao;
import com.dkm.modules.sys.menu.service.MenuService;
import com.dkm.modules.sys.menu.service.RoleMenuService;
import com.dkm.modules.sys.menu.service.impl.MenuCacheService;
import com.dkm.modules.sys.role.mapper.RoleMapper;
import com.dkm.modules.sys.role.mapper.UserRoleMapper;
import com.dkm.modules.sys.role.model.RolePO;
import com.dkm.modules.sys.role.model.UserRolePO;
import com.dkm.modules.sys.role.model.request.AddRoleRequest;
import com.dkm.modules.sys.role.model.request.EditRoleRequest;
import com.dkm.modules.sys.role.model.request.RoleMenuRequest;
import com.dkm.modules.sys.role.service.RoleService;
import com.dkm.modules.sys.user.model.UserRoles;
import com.dkm.util.StringUtils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @ClassName RoleServiceImpl
 * @Description: 实现类
 * @Author yangbin
 * @Date 2019-09-17 23:56
 * @Version V1.0
 **/
@Slf4j
@Service
public class RoleServiceImpl implements RoleService {


    @Autowired
    UniqueKeyDao uniqueKeyDao;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    MenuService menuService;

    @Autowired
    MenuCacheService menuCacheService;

    @Autowired
    RoleCacheService roleCacheService;


    @Override
    public void addRole(AddRoleRequest addRole) {
        String roleNam = addRole.getRoleName().trim();
        List<RolePO> allRole = this.getAllRole();
        if (CollectionUtils.isNotEmpty(allRole)) {
            allRole.stream().forEach(role -> {
                if (role.getRoleName().trim().equals(roleNam)) {
                    throw new ServiceException("角色名称已被占用,请换一个试试");
                }
            });
        }

        RolePO role = addRole.converToPO();

        this.setRoleCode(role);

        roleMapper.insert(role);

        // 清楚所有缓存
        roleCacheService.delAllRoleCache();
    }

    /**
     * 赋值roleCode,规则:全局唯一
     *
     * @param role
     */
    private void setRoleCode(RolePO role) {
        Integer uniqueCode = uniqueKeyDao.getUniqueCode();
        role.setRoleCode(uniqueCode);
    }

    @Override
    public void editRole(EditRoleRequest editRole) {
        String roleNam = editRole.getRoleName().trim();
        List<RolePO> allRole = this.getAllRole();
        if (CollectionUtils.isNotEmpty(allRole)) {
            allRole.stream().forEach(role -> {
                if (!editRole.getId().equals(role.getId()) && role.getRoleName().trim().equals(roleNam)) {
                    throw new ServiceException("角色名称已被占用,请换一个试试");
                }
            });
        }


        RolePO rolePO = editRole.converToPO();
        roleMapper.updateById(rolePO);
        roleCacheService.delAllRoleCache();
    }

    @Override
    public void delRole(Integer id) {
        roleMapper.deleteById(id);
        // 删除关联表里的角色

        menuCacheService.delAllMenuAndBtnCache();
        roleCacheService.delAllRoleCache();
    }

    @Override
    public IPage<RolePO> getRoleList(String keyWord, Page<RolePO> page) {
        QueryWrapper wrapper = new QueryWrapper();
        if (StringUtils.isNotEmpty(keyWord)) {
            wrapper.like("role_name", keyWord);
            wrapper.or();
            wrapper.like("description", keyWord);
        }

        Page page1 = roleMapper.selectPage(page, wrapper);
        return page1;
    }

    @Override
    public List<RolePO> getRoleSelect(Integer userId) {
        // 获取所有角色
        List<RolePO> allRole = this.getAllRole();
        if (CollectionUtils.isEmpty(allRole)) {
            return Lists.newArrayList();
        }
        // 获取用户的角色
        List<RolePO> userRole = this.getRoleByUserId(userId);
        if (CollectionUtils.isEmpty(userRole)) {
            return allRole;
        }
        List<Integer> userRoleCodes = userRole.stream().map(RolePO::getRoleCode).collect(Collectors.toList());
        allRole.stream().forEach(rolePO -> {
                    if (userRoleCodes.contains(rolePO.getRoleCode())) {
                        rolePO.setCheck(true);
                    }
                }
        );
        return allRole;
    }

    @Override
    public void saveRoleMenus(RoleMenuRequest roleMenus) {
        roleMenuService.insertOrUpdate(roleMenus);
        // 清空所有用户的菜单缓存
        menuCacheService.delAllMenuAndBtnCache();
    }

    /**
     * 查询所有角色信息
     *
     * @return
     */
    @Override
    public List<RolePO> getAllRole() {
        // 缓存取
        List<RolePO> cache = roleCacheService.getAllRoleFromCache();

        if (CollectionUtils.isNotEmpty(cache)) {
            return cache;
        }

        // 数据库取
        List<RolePO> rolePos = roleMapper.selectList(null);

        if (CollectionUtils.isNotEmpty(rolePos)) {
            roleCacheService.addAllRoleCache(rolePos);
        }
        return rolePos;
    }


    @Override
    public List<RolePO> getRoleByUserId(Integer userId) {
        // 所有角色
        List<RolePO> allRole = getAllRole();
        if (CollectionUtils.isEmpty(allRole)) {
            return Lists.newArrayList();
        }

        // 缓存取
        List<RolePO> roleByUserIdFromCache = roleCacheService.getRoleByUserIdFromCache(userId);

        if (CollectionUtils.isNotEmpty(roleByUserIdFromCache)) {
            return roleByUserIdFromCache;
        }
        // 数据库取
        Map<String, Object> param = new HashMap<>();
        param.put("user_id", userId);
        List<UserRolePO> userRolePOS = userRoleMapper.selectByMap(param);

        if (CollectionUtils.isNotEmpty(userRolePOS)) {
            List<Integer> userRoleCodes = userRolePOS.stream().map(UserRolePO::getRoleCode).collect(Collectors.toList());

            List<RolePO> userRoles = allRole.stream().filter(role -> userRoleCodes.contains(role.getRoleCode())).collect(Collectors.toList());

            // 新增缓存
            roleCacheService.addUserRoleCache(userId, userRoles);

            return userRoles;
        }

        return Lists.newArrayList();
    }

    @Transactional
    @Override
    public void updateUserRole(UserRoles roleResults) {
        Integer userId = roleResults.getId();
        if (Objects.isNull(userId)) {
            throw new ServiceException("配置用户角色,用户id不能为空");
        }

        // 清空数据库
        HashMap<String, Object> param = new HashMap<>();
        param.put("user_id", userId);
        userRoleMapper.deleteByMap(param);
        // 清空缓存
        roleCacheService.delUserRoleCache(userId);
        menuCacheService.delAllMenuAndBtnCache();

        List<Integer> roleCodes = roleResults.getRoleCodes();
        if (CollectionUtils.isEmpty(roleCodes)) {
            return;
        }
        // 新增数据库
        for (Integer roleCode : roleCodes) {
            userRoleMapper.insert(new UserRolePO(userId, roleCode));
        }
    }

}